#include "oled.h"


//OLED的显存
//存放格式如下.
//[0]0 1 2 3 ... 127	
//[1]0 1 2 3 ... 127	
//[2]0 1 2 3 ... 127	
//[3]0 1 2 3 ... 127	
//[4]0 1 2 3 ... 127	
//[5]0 1 2 3 ... 127	
//[6]0 1 2 3 ... 127	
//[7]0 1 2 3 ... 127 		

//初始化命令
uint8_t CMD_Data[]={
0xAE, 0x00, 0x10, 0x40, 0xB0, 0x81, 0xFF, 0xA1, 0xA6, 0xA8, 0x3F,
					
0xC8, 0xD3, 0x00, 0xD5, 0x80, 0xD8, 0x05, 0xD9, 0xF1, 0xDA, 0x12,
					
0xD8, 0x30, 0x8D, 0x14, 0xAF};


//向设备写控制命令
void OLED_WR_CMD(uint8_t cmd)
{
  /* <低电平是命令> */
  Data_Cmd_State(OLED_CMD);
  HAL_SPI_Transmit(&OLED_SPI, &cmd, 1, 0xff);
  /* <恢复> */
  Data_Cmd_State(1);  
}

//向设备写数据
void OLED_WR_DATA(uint8_t data)
{
  /* <高电平是数据> */
  Data_Cmd_State(OLED_DAT);
  HAL_SPI_Transmit(&OLED_SPI, &data, 1, 0xff);
  /* <恢复> */
  Data_Cmd_State(1);
}

//初始化oled屏幕
void OLED_Init(void)
{ 	
	OLED_RST_State(0);
	HAL_Delay(200);
	OLED_RST_State(1);

	for(int16_t i=0; i<sizeof(CMD_Data); i++)	
    OLED_WR_CMD(CMD_Data[i]);
	
	OLED_CLS();
}

//清屏size12 size16要清两行，其他函数有类似情况
void OLED_CLS(void)
{
	uint8_t i,n;		    
	for(i=0;i<8;i++)  
	{  
		OLED_WR_CMD(0xb0+i);
		OLED_WR_CMD (0x00); 
		OLED_WR_CMD (0x10); 
		for(n=0;n<128;n++)
			OLED_WR_DATA(0);
	} 
}

//清行
void OLED_CLSrow(uint8_t i)
{
	uint8_t n;
	OLED_WR_CMD(0xb0+i);
		OLED_WR_CMD (0x00); 
		OLED_WR_CMD (0x10); 
		for(n=0;n<128;n++)
			OLED_WR_DATA(0);
}

//开启OLED显示    
void OLED_ON(void)
{
	OLED_WR_CMD(0X8D);  //SET DCDC命令
	OLED_WR_CMD(0X14);  //DCDC ON
	OLED_WR_CMD(0XAF);  //DISPLAY ON
}

//关闭OLED显示     
void OLED_OFF(void)
{
	OLED_WR_CMD(0X8D);  //SET DCDC命令
	OLED_WR_CMD(0X10);  //DCDC OFF
	OLED_WR_CMD(0XAE);  //DISPLAY OFF
}		

void OLED_Set_Pos(uint8_t x, uint8_t y) 
{ 	
	OLED_WR_CMD(0xb0+y);
	OLED_WR_CMD(((x&0xf0)>>4)|0x10);
	OLED_WR_CMD(x&0x0f);
} 
 
void OLED_On(void)  
{  
	uint8_t i,n;		    
	for(i=0;i<8;i++)  
	{  
		OLED_WR_CMD(0xb0+i);    //设置页地址（0~7）
		OLED_WR_CMD(0x00);      //设置显示位置—列低地址
		OLED_WR_CMD(0x10);      //设置显示位置—列高地址   
		for(n=0;n<128;n++)
			OLED_WR_DATA(1); 
	} //更新显示
}


//显示汉字
//hzk 用取模软件得出的数组
//void OLED_ShowCHinese(uint8_t x,uint8_t y,uint8_t no)
//{      			    
//	uint8_t t,adder=0;
//	OLED_Set_Pos(x,y);	
//    for(t=0;t<16;t++)
//		{
//				OLED_WR_DATA(Hzk[2*no][t]);
//				adder+=1;
//     }	
//		OLED_Set_Pos(x,y+1);	
//    for(t=0;t<16;t++)
//			{	
//				OLED_WR_DATA(Hzk[2*no+1][t]);
//				adder+=1;
//      }					
//}

/**
 * @brief	在指定位置显示一幅图片
 * @param x1,x2  - 0 - 127
 * @param y1,y2  - 0 - 7(8表示全屏显示)
 * @param BMP - 图片数组地址
 * @note	图像数组BMP存放在bmp.h文件中
*/
void OLED_DrawBMP(uint8_t x0, uint8_t y0,uint8_t x1, uint8_t y1,uint8_t BMP[])
{ 	
 uint16_t j=0;
 uint8_t x,y;
  
//  if(y1%8==0)
//	{
//		y=y1/8;
//	}		
//  else
//	{
//		y=y1/8+1;
//	}
	for(y=y0;y<y1;y++)
	{
		OLED_Set_Pos(x0,y);
    for(x=x0;x<x1;x++)
	  {      
	    	OLED_WR_DATA(BMP[j++]);	   

	  }
	}
} 
/**
* @brief	全屏显示图片
 * @param BMP - 图片数组地址
 * @note	图像数组BMP存放在bmp.h文件中
*/
void OLED_FILL(uint8_t BMP[])			
{
  uint16_t j = 0;
  uint8_t x, y;
  
  for(y = 0; y<8; y++)
  {
    OLED_Set_Pos(0, y);
    
    for(x = 0; x<128; x++)    
      OLED_WR_DATA(BMP[j++]);    
  }
}
#if  1
/*
函数功能：显示汉字
参数：uint8_t x-->x坐标(0-127),uint8_t y-->y坐标(0-7),uint8_t w-->字体宽度,uint8_t h-->字体高度,
	 char *buff-->汉字,uint8_t align-->居中对齐(CEN_ALIGN)或不对齐(NO_ALIGN)
*/	
uint8_t OLED_Display_Chinese(uint8_t x,uint8_t y,uint8_t w,uint8_t h,char *buff,uint8_t align)
{
	uint8_t i,j;
	if(y>=8||x>=128) return 1;//是否超出范围
	if((align==CEN_ALIGN) && (64-(w/2))>=0)
	{
		x=64-(w/2);
	}
	for(i=0;i<(h/8);i++)
	{
		OLED_Set_Pos(x,y+i);
		for(j=0;j<w;j++)
		{
			OLED_WR_DATA(buff[j+i*w]);
		}
	}
	return 0;
}


/*
函数功能：显示字符
参数：uint8_t x(0-127),uint8_t y(0-7),uint8_t w,uint8_t h,char ch,
	  uint8_t reverse(reverse=REVERSE,则是白底黑字,reverse=NORMAL则是白字黑底),
	  uint8_t align-->居中对齐(CEN_ALIGN)或不对齐(NO_ALIGN)
返回值：无
*/
uint8_t OLED_Display_Char(uint8_t x,uint8_t y,uint8_t w,uint8_t h,char ch,uint8_t reverse,uint8_t align)
{
	uint8_t base=ch-' ';
	if(y>=8||x>=128) return 1;//是否超出范围
	if(align==CEN_ALIGN && (64-(w/2))>=0)
	{
		x=64-(w/2);
	}
	for(uint8_t j=0;j<(h/8);j++)//扫描页
	{
		OLED_Set_Pos(x,y+j);//设置坐标
		for(uint8_t i=0;i<w;i++)//扫描列,列地址自增
		{
			if(reverse==NORMAL)//白字黑底
			{
				if(w==8&&h==16)OLED_WR_DATA(ASCII_8x16[base*(w*h/8)+i+w*j]);
				else if(w==8&&h==8)OLED_WR_DATA(ASCII_8x8[base*(w*h/8)+i+w*j]);
				else if(w==16&&h==32) 
				{
					if(ch==':')
					{
						OLED_WR_DATA(Num_16x32[10*(w*h/8)+i+w*j]);
					}
					else OLED_WR_DATA(Num_16x32[(base-16)*(w*h/8)+i+w*j]);
				}
			}
			else//白底黑字
			{
				if(w==8&&h==16)OLED_WR_DATA(~ASCII_8x16[base*(w*h/8)+i+w*j]);
				else if(w==8&&h==8)OLED_WR_DATA(~ASCII_8x8[base*(w*h/8)+i+w*j]);
				else if(w==16&&h==32) 
				{
					if(ch==':')
					{
						OLED_WR_DATA(~Num_16x32[10*(w*h/8)+i+w*j]);
					}
					else OLED_WR_DATA(~Num_16x32[(base-16)*(w*h/8)+i+w*j]);
				}
			}
			
		}
	}
	return 0;
}

/*
函数功能：显示字符串
参数：uint8_t x(0-127),uint8_t y(0-7),uint8_t w,uint8_t h,char *str,
	 uint8_t reverse(reverse=REVERSE,则是白底黑字,reverse=NORMAL则是白字黑底),
	 uint8_t align-->居中对齐(CEN_ALIGN)或不对齐(NO_ALIGN)
返回值：超出范围返回1,成功返回0
*/
uint8_t OLED_Display_String(uint8_t x,uint8_t y,uint8_t w,uint8_t h,char *str,uint8_t reverse,uint8_t align)
{
	if(y>=8||x>=128) return 1;//是否超出范围
	if((align==CEN_ALIGN) && (int)(64-(w*strlen(str)/2))>=0)
	{
		x=64-(w*strlen(str)/2);
	}
	while(*str!='\0')
	{
		OLED_Display_Char(x,y,w,h,*str,reverse,NORMAL);//显示字符
		x+=w;//将x坐标移至下一个显示位置
		if(x>=128) return 1;//是否超出范围
		str++;//指针偏移
	}
	return 0;
}
/*
函数功能：显示图片
参数：uint8_t x(0-127),uint8_t y(0-7),uint8_t w,uint8_t h,char *img(图片数组),
	 uint8_t align-->居中对齐(CEN_ALIGN)或不对齐(NO_ALIGN)
返回值：无
*/
uint8_t OLED_Display_Image(uint8_t x,uint8_t y,uint8_t w,uint8_t h,char *img,uint8_t align)
{
	uint8_t tmp=0;
	
	if(y>=8||x>=128) return 1;//是否超出范围
	if((align==CEN_ALIGN) && (64-(w/2))>=0)
	{
		x=64-(w/2);
	}
	
	tmp=h/8;
	if(h%8) tmp+=1;
	for(uint8_t j=0;j<tmp;j++)//扫描页
	{
		OLED_Set_Pos(x,y+j);//设置坐标
		for(uint8_t i=0;i<w;i++)//扫描列,列地址自增
		{
			OLED_WR_DATA(img[i+w*j]);
		}
	}
	return 0;
}

#endif
